// This demonstrates 2-sided lighting.  The front and back 
// of the spinning rectangle are given different
// material properties.


	
import java.awt.BorderLayout;
import java.awt.Frame;
import java.awt.GridLayout;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.media.opengl.*;
import javax.media.opengl.glu.*;
import javax.media.opengl.awt.GLCanvas;
import com.jogamp.opengl.util.*;
import java.awt.*;
import javax.swing.*;

import java.awt.event.*;
import javax.swing.event.*;



public class SpinningRectangle implements GLEventListener, ActionListener, ChangeListener {
	
	public static void main(String[] args) {
		new SpinningRectangle();
	}
	
	private int INTITIAL_WIDTH=800;
	private int INITIAL_HEIGHT=800;
	
	JButton quitButton;
	private GLCanvas canvas;
	private GL2 gl;
	private GLU glu;
	private JSlider xSlider, ySlider, zSlider;
	
	private float ambient[] = {0.3f, 0f, 0f, 1f};
	private float specular[] = {0.9f, 0.9f, 0.9f, 1f};
	private float shininess = 64f;
	private float redPlasticDiffuse[] = {0.9f, 0f, 0f, 1f};
	private float greenPlasticDiffuse[] = {0f, 0.9f, 0f, 1f};
	
	private float lightAmbient[] = {0f, 0f, 0f, 1f};
	private float lightDiffuse[] = {1f, 1f, 1f, 1f};
	private float lightSpecular[] = {1f, 1f, 1f, 1f};
	
	private float lightPosition[] = {30f, 10f, 10f, 1f};
	
	// The viewer is at (2, 0, 0); this doesn't change.
	private float viewerX = 50f;
	private float viewerY  = 0f;
	private float viewerZ = 0f;
	
	private float theta = 60;
	

	public  SpinningRectangle() {
			GLProfile glp=GLProfile.getDefault();
			GLCapabilities caps = new GLCapabilities(glp);
			canvas = new GLCanvas(caps);
			JFrame frame = new JFrame("SPINNING RECTANGLE");

			frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE );
			frame.setSize(800, 800);
			frame.setLayout(new BorderLayout());
			JPanel north = new JPanel( new BorderLayout());
			JPanel topRow = new JPanel( new FlowLayout(FlowLayout.LEADING));
			
			quitButton = new JButton( "Quit");
			quitButton.addActionListener(this);
			topRow.add(quitButton);

			north.add(topRow, BorderLayout.NORTH);
			
			JPanel south = new JPanel(new GridLayout(3, 1));
			JPanel secondRow = new JPanel(new BorderLayout());
			JPanel thirdRow = new JPanel( new BorderLayout());
			JPanel fourthRow = new JPanel( new BorderLayout() );
			xSlider = new JSlider(-100, 100);
			xSlider.setValue((int)(lightPosition[0]));
			xSlider.setMajorTickSpacing(20);
			xSlider.setPaintTicks(true);
			xSlider.setPaintLabels(true);
			xSlider.addChangeListener(this);
			JLabel xSliderName = new JLabel("   Light X");
			secondRow.add(xSliderName, BorderLayout.WEST);
			secondRow.add(xSlider, BorderLayout.CENTER);
			south.add(secondRow);
			ySlider = new JSlider(-100, 100);
			ySlider.setValue((int)(lightPosition[1]));
			ySlider.setMajorTickSpacing(20);
			ySlider.setPaintTicks(true);
			ySlider.setPaintLabels(true);
			ySlider.addChangeListener(this);
			JLabel ySliderName = new JLabel(" Light Y");
			thirdRow.add(ySliderName, BorderLayout.WEST);
			thirdRow.add(ySlider, BorderLayout.CENTER);
			south.add(thirdRow);
			zSlider = new JSlider(-100, 100);
			zSlider.setValue((int)(lightPosition[2]));
			zSlider.setMajorTickSpacing(20);
			zSlider.setPaintTicks(true);
			zSlider.setPaintLabels(true);
			zSlider.addChangeListener(this);
			JLabel zSliderName = new JLabel("  Light Z");
			fourthRow.add(zSliderName, BorderLayout.WEST);
			fourthRow.add(zSlider, BorderLayout.CENTER);
			south.add(fourthRow);
			

			north.add(south, BorderLayout.SOUTH);
			frame.add(north, BorderLayout.NORTH);
			JPanel myCanvas = new JPanel(new GridLayout(1,1));
			
			myCanvas.add(canvas);

			frame.add(myCanvas, BorderLayout.CENTER);
			
			frame.setVisible(true);
			canvas.addGLEventListener(this);

			FPSAnimator animator = new FPSAnimator(canvas, 60);
			animator.start(); 
				

	}
	public void actionPerformed(ActionEvent event) {
			if (event.getSource() == quitButton)
				System.exit(0);

	}
	
	public void stateChanged(ChangeEvent e) {
		if (e.getSource() == xSlider) {
			lightPosition[0] = xSlider.getValue();
		}
		else if (e.getSource() == ySlider) {
			lightPosition[1] = ySlider.getValue();
		}
		else if (e.getSource() == zSlider) {
			lightPosition[2] = zSlider.getValue();
		}

	}

	public void display(GLAutoDrawable drawable) {
		update();
		render(drawable);
	}

	private void update() {			
		theta += 1;
	}

	
	private void render(GLAutoDrawable drawable) {
		int Divisions = 20;
		
		gl.glClear(GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT);
		gl.glLightfv(GL2.GL_LIGHT0,  GL2.GL_POSITION, lightPosition, 0);

		gl.glPushMatrix();
		gl.glRotatef(theta, 0f, 1f, 0f);
		square( Divisions );
		gl.glPopMatrix();
	}
	
	// This makes a square that is 20 units on each side;
	// it is divided into divisionsxdivisions subsquares
	private void square(int divisions) {
		float left = -10f;
		float right = 10f;
		float top = -10f;
		float bottom = 10f;
		float delta = 20f/divisions;
		
		gl.glNormal3f(1f, 0f, 0f);
		for (float y = left; y < right; y += delta) {
			for (float z = top; z < bottom; z += delta) {
				gl.glBegin(GL2.GL_POLYGON);
				gl.glVertex3f(0f, y, z);
				gl.glVertex3f(0f, y+delta, z);
				gl.glVertex3f(0f,  y+delta, z+delta);
				gl.glVertex3f(0f, y, z+delta);
				gl.glEnd();
			}
		}
	}
	
	public void dispose(GLAutoDrawable drawable) {
		// put the cleanup code here
		
	}

	public void init(GLAutoDrawable drawable) {
		gl = drawable.getGL().getGL2();
		glu = new GLU();
		

		gl.glEnable(GL2.GL_DEPTH_TEST);
		
		gl.glEnable(GL2.GL_LIGHTING);
		gl.glLightModelf(GL2.GL_LIGHT_MODEL_TWO_SIDE, GL2.GL_TRUE);
		gl.glEnable(GL2.GL_LIGHT0);
		
		gl.glMatrixMode(GL2.GL_PROJECTION);
		gl.glLoadIdentity();
		glu.gluPerspective(60f, 1f, 0.5f, 200f); 
		gl.glMatrixMode(GL2.GL_MODELVIEW);
		gl.glLoadIdentity();
		glu.gluLookAt(viewerX, viewerY, viewerZ, 0f, 0f, 0f, 0f, 0f, 1f);
		gl.glClearColor(1,  1, 1, 1);
		gl.glClear(GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT);
		
		gl.glLightfv(GL2.GL_LIGHT0,  GL2.GL_AMBIENT, lightAmbient, 0);
		gl.glLightfv(GL2.GL_LIGHT0,  GL2.GL_DIFFUSE, lightDiffuse, 0);
		gl.glLightfv(GL2.GL_LIGHT0,  GL2.GL_SPECULAR, lightSpecular, 0);
		gl.glLightfv(GL2.GL_LIGHT0,  GL2.GL_POSITION, lightPosition, 0);

		gl.glMaterialfv(GL2.GL_FRONT, GL2.GL_AMBIENT, ambient, 0);
		gl.glMaterialfv(GL2.GL_FRONT, GL2.GL_DIFFUSE, redPlasticDiffuse, 0);
		gl.glMaterialfv(GL2.GL_FRONT, GL2.GL_SPECULAR, specular, 0);
		gl.glMaterialf(GL2.GL_FRONT, GL2.GL_SHININESS, shininess);
		
		gl.glMaterialfv(GL2.GL_BACK, GL2.GL_AMBIENT, ambient, 0);
		gl.glMaterialfv(GL2.GL_BACK, GL2.GL_DIFFUSE, greenPlasticDiffuse, 0);
		gl.glMaterialfv(GL2.GL_BACK, GL2.GL_SPECULAR, specular, 0);
		gl.glMaterialf(GL2.GL_BACK, GL2.GL_SHININESS, shininess);

	}

	public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
		// this is called when the window is resized
		gl.glViewport(0, 0, width, height);
		float aspect = width*1.0f/height;
		gl.glMatrixMode(GL2.GL_PROJECTION);
		gl.glLoadIdentity();
		glu.gluPerspective(60f, aspect, 0.5f, 200f); 
		gl.glMatrixMode(GL2.GL_MODELVIEW);
		
		
	}
	
}
